package cn.thoughtworks.school.usercenter.controllers;

import cn.thoughtworks.school.usercenter.entities.EmailReset;
import cn.thoughtworks.school.usercenter.entities.User;
import cn.thoughtworks.school.usercenter.exceptions.BusinessException;
import cn.thoughtworks.school.usercenter.repositories.EmailResetRepository;
import cn.thoughtworks.school.usercenter.repositories.UserRepository;
import cn.thoughtworks.school.usercenter.services.SendEmailService;
import cn.thoughtworks.school.usercenter.utils.EmailResetStatus;
import cn.thoughtworks.school.usercenter.utils.Tool;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.sql.Timestamp;
import java.util.*;

@RestController
@RequestMapping(value = "/api/email-reset")
public class EmailResetController {
    public static final Long DURATION = (long) (30 * 60);

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private EmailResetRepository emailResetRepository;

    @Autowired
    private SendEmailService sendEmailService;

    @Value("${emailDomain.resetEmail}")
    private String resetEmailDomain;

    @PostMapping(value = "/users/{id}")
    ResponseEntity createEmailResetRequest(@RequestBody Map<String, String> emailInfo, @PathVariable(value = "id") String id) throws Exception {
        String email = emailInfo.get("email");
        String subject = "修改绑定邮箱确认邮件"; //can be refactor
        Boolean flag = isEmailDuplicate(email);
        if (flag) {
            throw new BusinessException("邮箱已经存在，请您更换邮箱！");
        }
        EmailReset emailReset = createEmailResetData(id, email);
        String emailAddress = resetEmailDomain + "/" + emailReset.getUuid();
        String emailContent = "您在浏览我们网站时使用了修改绑定邮箱功能，这是一封修改绑定邮箱确认邮件。\n 您可以通过点击以下链接修改绑定邮箱:\n" + emailAddress + "\n为保障您的帐号安全，请在30分钟内点击该链接，您也可以将链接复制到浏览器地址栏访问。\n 若如果您并未尝试修改绑定邮箱，请忽略本邮件，由此给您带来的不便请谅解。本邮件由系统自动发出,请勿直接回复!";
        HttpResponse response = sendEmailService.sendEmail(email, subject, emailContent);
        int statusCode = response.getStatusLine().getStatusCode();
        Map<String, String> responseBody = new HashMap<>();
        responseBody.put("email", email);

        if (statusCode == HttpStatus.OK.value()) {
            responseBody.put("status", EmailResetStatus.PENDING.toString());
        } else {
            emailReset.setStatus(EmailResetStatus.FAILURE);
            emailResetRepository.save(emailReset);
            responseBody.put("status", EmailResetStatus.FAILURE.toString());
        }

        return new ResponseEntity<Map>(responseBody, HttpStatus.CREATED);
    }

    private EmailReset createEmailResetData(String id, String email) {
        Long userId = Long.parseLong(id);
        EmailResetStatus status = EmailResetStatus.PENDING;

        return emailResetRepository.save(new EmailReset(userId, email, status, new Timestamp(Tool.getUTCTimeStamp())));
    }

    private Boolean isEmailDuplicate(String email) {
        User user = userRepository.findByEmail(email);
        return user != null;
    }

    private   Boolean isLatest(String uuid) {
        EmailReset emailReset = emailResetRepository.findByUuid(uuid);
        Long userId = emailReset.getUserId();
        List<EmailReset> emailResetList = emailResetRepository.getEmailResetByUserIdOrderByCreateTimeDesc(userId);
        EmailReset latestEmailReset = emailResetList.get(0);
        String Uuid = latestEmailReset.getUuid();
        return Objects.equals(uuid, Uuid);
    }

    @PutMapping(value = "/{uuid}")
    ResponseEntity updateEmail(@PathVariable String uuid) throws BusinessException {
        EmailReset emailReset = emailResetRepository.findByUuid(uuid);
        Boolean isExpired = Tool.isExpired(emailReset.getCreateTime(), DURATION);
        Boolean isLatest = isLatest(uuid);
        Map<String, String> resBody = new HashMap<>();
        Long userId = emailReset.getUserId();
        String email = emailReset.getEmail();

        if (isExpired && isLatest) {
            emailReset.setStatus(EmailResetStatus.FAILURE);
            resBody.put("message", "确认邮件链接已过期,请重新绑定!");
            resBody.put("status", EmailResetStatus.FAILURE.toString());
        } else if (isExpired){
            emailReset.setStatus(EmailResetStatus.PENDING);
            resBody.put("message", "该邮件链接已经失效，请点击最新邮件中的链接");
            resBody.put("status", EmailResetStatus.PENDING.toString());
        }else {
            emailReset.setStatus(EmailResetStatus.SUCCESS);
            User user = userRepository.findById(userId).orElseThrow(() -> new BusinessException("当前用户不存在"));
            user.setEmail(email);
            userRepository.save(user);
            resBody.put("message", "修改绑定邮箱成功！请回到系统中刷新页面，查看绑定结果！");
            resBody.put("status", EmailResetStatus.SUCCESS.toString());
        }

        emailResetRepository.save(emailReset);
        return new ResponseEntity<Map>(resBody, HttpStatus.OK);
    }

    @GetMapping(value = "/users/{id}")
    ResponseEntity getResetEmailStatus(@PathVariable(value = "id") String id) {
        List<EmailReset> emailResetList = emailResetRepository.getByUserId(Long.parseLong(id));

        if (emailResetList.size() == 0) {
            Map<String, EmailResetStatus> result = new HashMap<>();
            result.put("status", EmailResetStatus.SUCCESS);
            return new ResponseEntity(result, HttpStatus.OK);
        }


        emailResetList.sort(new Comparator<EmailReset>() {
            public int compare(EmailReset arg0, EmailReset arg1) {
                return arg0.getCreateTime().compareTo(arg1.getCreateTime());
            }
        });  //refactor: move sort into mysql

        EmailReset emailReset = emailResetList.get(emailResetList.size() - 1);

        Map<String, String> responseBody = new HashMap<>();
        responseBody.put("status", emailReset.getStatus().toString());
        responseBody.put("email", emailReset.getEmail());

        return new ResponseEntity<Map>(responseBody, HttpStatus.OK);
    }
}
